# -*- coding: utf-8 -*-
"""
乒乓球培训管理系统 - 认证表单
表单层，用户认证相关的表单定义
支持Flask-WTF表单验证和CSRF保护
"""

import re
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed
from wtforms import StringField, PasswordField, BooleanField, SubmitField, SelectField, TextAreaField, IntegerField
from wtforms.validators import DataRequired, Length, Email, Optional, ValidationError, Regexp, NumberRange
from app.models.user import User
from app.models.campus import Campus


class LoginForm(FlaskForm):
    """
    用户登录表单

    支持用户名/手机号登录、密码、记住我选项
    支持表单验证和自定义验证器
    """

    username = StringField(
        '用户名/手机号',
        validators=[
            DataRequired(message='请输入用户名或手机号'),
            Length(min=3, max=50, message='用户名长度应在3-50个字符之间')
        ],
        render_kw={
            'class': 'form-control',
            'placeholder': '请输入用户名或手机号',
            'autocomplete': 'username'
        }
    )

    password = PasswordField(
        '密码',
        validators=[
            DataRequired(message='请输入密码'),
            Length(min=8, max=16, message='密码长度应在8-16个字符之间')
        ],
        render_kw={
            'class': 'form-control',
            'placeholder': '请输入密码',
            'autocomplete': 'current-password'
        }
    )

    remember_me = BooleanField(
        '记住我',
        render_kw={
            'class': 'form-check-input'
        }
    )

    submit = SubmitField(
        '登录',
        render_kw={
            'class': 'btn btn-primary w-100'
        }
    )

    def validate_username(self, field):
        """
        验证用户名是否存在

        Args:
            field: 用户名字段

        Raises:
            ValidationError: 用户名不存在时抛出异常
        """
        user = User.query.filter(
            (User.username == field.data) | (User.phone == field.data)
        ).first()
        if not user:
            raise ValidationError('用户名或手机号不存在，请检查后重新输入')

        if user.status == 'inactive':
            raise ValidationError('该账户已被禁用，请联系管理员')
        elif user.status == 'pending':
            raise ValidationError('该账户待审核，请等待管理员审核通过')

    def validate_password(self, field):
        """
        验证密码是否正确

        Args:
            field: 密码字段

        Raises:
            ValidationError: 密码错误时抛出异常
        """
        if self.username.data:
            user = User.query.filter(
                (User.username == self.username.data) | (User.phone == self.username.data)
            ).first()
            if user and not user.check_password(field.data):
                raise ValidationError('密码错误，请重新输入')

    def get_user(self):
        """
        获取验证通过的用户对象

        Returns:
            User: 用户对象，如果验证失败返回None
        """
        if self.validate():
            return User.query.filter(
                (User.username == self.username.data) | (User.phone == self.username.data)
            ).first()
        return None


class StudentRegistrationForm(FlaskForm):
    """
    学员注册表单

    包含学员注册所需的基本信息
    注册后状态为active，无需审核
    """

    username = StringField(
        '用户名',
        validators=[
            DataRequired(message='请输入用户名'),
            Length(min=3, max=50, message='用户名长度应在3-50个字符之间'),
            Regexp('^[a-zA-Z0-9_]+$', message='用户名只能包含字母、数字和下划线')
        ],
        render_kw={
            'class': 'form-control',
            'placeholder': '请输入用户名（字母、数字、下划线）'
        }
    )

    password = PasswordField(
        '密码',
        validators=[
            DataRequired(message='请输入密码'),
            Length(min=8, max=16, message='密码长度应在8-16个字符之间')
        ],
        render_kw={
            'class': 'form-control',
            'placeholder': '8-16位，包含字母和数字'
        }
    )

    confirm_password = PasswordField(
        '确认密码',
        validators=[
            DataRequired(message='请确认密码')
        ],
        render_kw={
            'class': 'form-control',
            'placeholder': '请再次输入密码'
        }
    )

    real_name = StringField(
        '真实姓名',
        validators=[
            DataRequired(message='请输入真实姓名'),
            Length(min=2, max=50, message='姓名长度应在2-50个字符之间')
        ],
        render_kw={
            'class': 'form-control',
            'placeholder': '请输入真实姓名'
        }
    )

    phone = StringField(
        '手机号',
        validators=[
            DataRequired(message='请输入手机号'),
            Regexp('^1[3-9]\d{9}$', message='请输入正确的手机号格式')
        ],
        render_kw={
            'class': 'form-control',
            'placeholder': '请输入11位手机号'
        }
    )

    email = StringField(
        '邮箱',
        validators=[
            Optional(),
            Email(message='请输入正确的邮箱格式')
        ],
        render_kw={
            'class': 'form-control',
            'placeholder': '请输入邮箱（可选）'
        }
    )

    gender = SelectField(
        '性别',
        choices=[('', '请选择'), ('male', '男'), ('female', '女')],
        validators=[Optional()],
        render_kw={
            'class': 'form-select'
        }
    )

    age = IntegerField(
        '年龄',
        validators=[
            Optional(),
            NumberRange(min=5, max=99, message='年龄应在5-99岁之间')
        ],
        render_kw={
            'class': 'form-control',
            'placeholder': '请输入年龄（可选）'
        }
    )

    campus_id = SelectField(
        '所属校区',
        coerce=int,
        validators=[DataRequired(message='请选择所属校区')],
        render_kw={
            'class': 'form-select'
        }
    )

    submit = SubmitField(
        '注册',
        render_kw={
            'class': 'btn btn-primary w-100'
        }
    )

    def __init__(self, *args, **kwargs):
        super(StudentRegistrationForm, self).__init__(*args, **kwargs)
        # 动态加载校区选项
        self.campus_id.choices = [(0, '请选择校区')] + [
            (campus.id, campus.name) for campus in Campus.query.all()
        ]

    def validate_username(self, field):
        """验证用户名唯一性"""
        user = User.query.filter_by(username=field.data).first()
        if user:
            raise ValidationError('该用户名已被注册，请选择其他用户名')

    def validate_phone(self, field):
        """验证手机号唯一性"""
        user = User.query.filter_by(phone=field.data).first()
        if user:
            raise ValidationError('该手机号已被注册，请使用其他手机号')

    def validate_email(self, field):
        """验证邮箱唯一性"""
        if field.data:
            user = User.query.filter_by(email=field.data).first()
            if user:
                raise ValidationError('该邮箱已被注册，请使用其他邮箱')

    def validate_password(self, field):
        """验证密码复杂度"""
        password = field.data
        if not re.search(r'[a-zA-Z]', password):
            raise ValidationError('密码必须包含字母')
        if not re.search(r'\d', password):
            raise ValidationError('密码必须包含数字')

    def validate_confirm_password(self, field):
        """验证密码确认"""
        if field.data != self.password.data:
            raise ValidationError('两次输入的密码不一致')

    def validate_campus_id(self, field):
        """验证校区选择"""
        if field.data == 0:
            raise ValidationError('请选择所属校区')


class CoachRegistrationForm(FlaskForm):
    """
    教练注册表单

    包含教练注册所需的基本信息和专业信息
    注册后状态为pending，需要校区管理员审核
    """

    username = StringField(
        '用户名',
        validators=[
            DataRequired(message='请输入用户名'),
            Length(min=3, max=50, message='用户名长度应在3-50个字符之间'),
            Regexp('^[a-zA-Z0-9_]+$', message='用户名只能包含字母、数字和下划线')
        ],
        render_kw={
            'class': 'form-control',
            'placeholder': '请输入用户名（字母、数字、下划线）'
        }
    )

    password = PasswordField(
        '密码',
        validators=[
            DataRequired(message='请输入密码'),
            Length(min=8, max=16, message='密码长度应在8-16个字符之间')
        ],
        render_kw={
            'class': 'form-control',
            'placeholder': '8-16位，包含字母和数字'
        }
    )

    confirm_password = PasswordField(
        '确认密码',
        validators=[
            DataRequired(message='请确认密码')
        ],
        render_kw={
            'class': 'form-control',
            'placeholder': '请再次输入密码'
        }
    )

    real_name = StringField(
        '真实姓名',
        validators=[
            DataRequired(message='请输入真实姓名'),
            Length(min=2, max=50, message='姓名长度应在2-50个字符之间')
        ],
        render_kw={
            'class': 'form-control',
            'placeholder': '请输入真实姓名'
        }
    )

    phone = StringField(
        '手机号',
        validators=[
            DataRequired(message='请输入手机号'),
            Regexp('^1[3-9]\d{9}$', message='请输入正确的手机号格式')
        ],
        render_kw={
            'class': 'form-control',
            'placeholder': '请输入11位手机号'
        }
    )

    email = StringField(
        '邮箱',
        validators=[
            Optional(),
            Email(message='请输入正确的邮箱格式')
        ],
        render_kw={
            'class': 'form-control',
            'placeholder': '请输入邮箱（可选）'
        }
    )

    gender = SelectField(
        '性别',
        choices=[('', '请选择'), ('male', '男'), ('female', '女')],
        validators=[Optional()],
        render_kw={
            'class': 'form-select'
        }
    )

    age = IntegerField(
        '年龄',
        validators=[
            Optional(),
            NumberRange(min=18, max=65, message='年龄应在18-65岁之间')
        ],
        render_kw={
            'class': 'form-control',
            'placeholder': '请输入年龄（可选）'
        }
    )

    campus_id = SelectField(
        '应聘校区',
        coerce=int,
        validators=[DataRequired(message='请选择应聘校区')],
        render_kw={
            'class': 'form-select'
        }
    )

    coach_level = SelectField(
        '申请级别',
        choices=[
            ('', '请选择'),
            ('junior', '初级教练（80元/小时）'),
            ('middle', '中级教练（150元/小时）'),
            ('senior', '高级教练（200元/小时）')
        ],
        validators=[DataRequired(message='请选择申请级别')],
        render_kw={
            'class': 'form-select'
        }
    )

    bio = TextAreaField(
        '个人简介',
        validators=[
            DataRequired(message='请填写个人简介'),
            Length(min=20, max=500, message='个人简介应在20-500个字符之间')
        ],
        render_kw={
            'class': 'form-control',
            'rows': 4,
            'placeholder': '请简要介绍自己的背景和特长（20-500字）'
        }
    )

    experience = TextAreaField(
        '教学经验',
        validators=[
            DataRequired(message='请填写教学经验'),
            Length(min=20, max=1000, message='教学经验应在20-1000个字符之间')
        ],
        render_kw={
            'class': 'form-control',
            'rows': 6,
            'placeholder': '请详细描述您的乒乓球教学经验、获得的荣誉、特长等（20-1000字）'
        }
    )

    photo = FileField(
        '个人照片',
        validators=[
            Optional(),
            FileAllowed(['jpg', 'jpeg', 'png', 'gif'], '只支持jpg、jpeg、png、gif格式的图片')
        ],
        render_kw={
            'class': 'form-control',
            'accept': 'image/*'
        }
    )

    submit = SubmitField(
        '提交申请',
        render_kw={
            'class': 'btn btn-primary w-100'
        }
    )

    def __init__(self, *args, **kwargs):
        super(CoachRegistrationForm, self).__init__(*args, **kwargs)
        # 动态加载校区选项
        self.campus_id.choices = [(0, '请选择校区')] + [
            (campus.id, campus.name) for campus in Campus.query.all()
        ]

    def validate_username(self, field):
        """验证用户名唯一性"""
        user = User.query.filter_by(username=field.data).first()
        if user:
            raise ValidationError('该用户名已被注册，请选择其他用户名')

    def validate_phone(self, field):
        """验证手机号唯一性"""
        user = User.query.filter_by(phone=field.data).first()
        if user:
            raise ValidationError('该手机号已被注册，请使用其他手机号')

    def validate_email(self, field):
        """验证邮箱唯一性"""
        if field.data:
            user = User.query.filter_by(email=field.data).first()
            if user:
                raise ValidationError('该邮箱已被注册，请使用其他邮箱')

    def validate_password(self, field):
        """验证密码复杂度"""
        password = field.data
        if not re.search(r'[a-zA-Z]', password):
            raise ValidationError('密码必须包含字母')
        if not re.search(r'\d', password):
            raise ValidationError('密码必须包含数字')

    def validate_confirm_password(self, field):
        """验证密码确认"""
        if field.data != self.password.data:
            raise ValidationError('两次输入的密码不一致')

    def validate_campus_id(self, field):
        """验证校区选择"""
        if field.data == 0:
            raise ValidationError('请选择应聘校区')


class PasswordChangeForm(FlaskForm):
    """
    密码修改表单

    用于用户修改自己的密码
    """

    current_password = PasswordField(
        '当前密码',
        validators=[
            DataRequired(message='请输入当前密码')
        ],
        render_kw={
            'class': 'form-control',
            'placeholder': '请输入当前密码'
        }
    )

    new_password = PasswordField(
        '新密码',
        validators=[
            DataRequired(message='请输入新密码'),
            Length(min=8, max=16, message='密码长度应在8-16个字符之间')
        ],
        render_kw={
            'class': 'form-control',
            'placeholder': '8-16位，包含字母和数字'
        }
    )

    confirm_new_password = PasswordField(
        '确认新密码',
        validators=[
            DataRequired(message='请确认新密码')
        ],
        render_kw={
            'class': 'form-control',
            'placeholder': '请再次输入新密码'
        }
    )

    submit = SubmitField(
        '修改密码',
        render_kw={
            'class': 'btn btn-primary'
        }
    )

    def __init__(self, user, *args, **kwargs):
        super(PasswordChangeForm, self).__init__(*args, **kwargs)
        self.user = user

    def validate_current_password(self, field):
        """验证当前密码是否正确"""
        if not self.user.check_password(field.data):
            raise ValidationError('当前密码错误')

    def validate_new_password(self, field):
        """验证新密码复杂度"""
        password = field.data
        if not re.search(r'[a-zA-Z]', password):
            raise ValidationError('密码必须包含字母')
        if not re.search(r'\d', password):
            raise ValidationError('密码必须包含数字')
        if field.data == self.current_password.data:
            raise ValidationError('新密码不能与当前密码相同')

    def validate_confirm_new_password(self, field):
        """验证新密码确认"""
        if field.data != self.new_password.data:
            raise ValidationError('两次输入的新密码不一致')
